// 购物车模块
import { mergeLocalCart, findCartList, insertCart, deleteCart, updateCart, checkAllCart } from '@/api/cart'
export default {
  namespaced: true,
  // 存数据
  state: () => ({
    list: [] // 购物车列表
  }),
  //   唯一能改变state的数据
  mutations: {
    insertCart (state, goods) { // 添加购物车逻辑
      console.log('加入购物车成功，商品信息：', goods)
      // 加入之前做判断
      // 如果当前添加的商品skuId和之前完全一致，则只做数量增加，否则就添加新项
      // 数组查找：find(找到之后操作数据字段用这个)返回查找项 和 findIndex(删除字段用这个) 返回查找项的索引
      const item = state.list.find(item => item.skuId === goods.skuId)
      if (item) { // 如果能找到
        // 只做数量的叠加
        item.count = item.count + goods.count
      } else {
        // 把当前传下来的goods字段加入 list中，unshift()
        state.list.unshift(goods)
      }
    },
    // 删除购物车商品 根据唯一的skuId查找到删除
    delCart (state, payload) {
      const index = state.list.findIndex(item => item.skuId === payload.skuId)
      state.list.splice(index, 1)
    },
    // 根据单选框状态，修改list中的selected字段
    singleCheck (state, { goods, selected }) {
      console.log('state', state)
      // 通过 goods中 skuId 找到当前要操作的项
      // 把传下来的selected状态，交给找到的selected字段
      const item = state.list.find(item => item.skuId === goods.skuId)
      item.selected = selected
    },
    // 全选框选中 => 所有单选框都选中
    allCheck (state, checked) {
      // 遍历
      state.list.forEach(item => { item.selected = checked })
    },
    // 修改数量
    changeNum (state, { goods, num }) {
      const item = state.list.find(item => item.skuId === goods.skuId)
      item.count = num
    },
    // 覆盖本地list
    changeList (state, newList) {
      state.list = newList
    }
  },
  //   异步 + mutation
  actions: {
    // 加入购物车
    asyncInsertCart (ctx, goods) { // 同步后台数据
      // 1. 区分登录和非登陆状态
      // 2. 业务组件里想要通过dispatch().then()获取数据
      // 好处两个：一是做一个操作逻辑的收敛 登录(异步)还是非登陆(同步) 都可以调用同一个action函数;
      // 二是封装成return new Promise 之后，可以再业务组件中 dispatch().then() 中执行后续逻辑
      return new Promise((resolve, reject) => {
        // 登陆之后 (token 跨模块使用数据)
        if (ctx.rootState.user.profile.token) { // 有token
          insertCart({ skuId: goods.skuId, count: goods.count }).then(res => {
            // 拉取最新的购物车列表
            findCartList().then(res => {
              // 后端返回的购物车列表覆盖到本地的购物车列表 以后端的列表数据为主
              ctx.commit('changeList', res.result)
            })
          })
          resolve()
        } else { // 非登录时
          ctx.commit('insertCart', goods)
          resolve() // 传递成功结果
        }
      })
    },
    // 删除购物车商品
    asyncDelCart (ctx, goods) {
      return new Promise((resolve, reject) => {
        if (ctx.rootState.user.profile.token) { // 登录 TODO
          const skuId = goods.skuId
          // (1) 调用删除购物车接口
          deleteCart([skuId]).then(res => {
            // (2) 获取最新的数据
            findCartList().then(res => {
              // 后端返回的购物车列表覆盖到本地的购物车列表
              ctx.commit('changeList', res.result)
              resolve()
            })
          })
        } else { // 非登陆
          ctx.commit('delCart', goods)
          resolve()
        }
      })
    },
    // 单选 是否选中商品  selected字段
    asyncSingleCheck (ctx, { goods, selected }) {
      console.log('ctx', ctx)
      return new Promise((resolve, reject) => {
        ctx.commit('singleCheck', { goods, selected })
        if (ctx.rootState.user.profile.token) { // 已登录 TODO
          // 准备参数
          const params = {
            skuId: goods.skuId,
            selected: goods.selected,
            count: goods.count
          }
          // (1) 发送接口
          updateCart(params).then(res => {
            // (2) 重新拉取数据
            findCartList().then(res => {
              // 后端返回的购物车列表覆盖到本地的购物车列表
              ctx.commit('changeList', res.result)
            })
          })
        } else { // 非登陆
          ctx.commit('singleCheck', { goods, selected })
          resolve()
        }
      })
    },
    // 全选框
    asyncAllCheck (ctx, checked) {
      return new Promise((resolve, reject) => {
        if (ctx.rootState.user.profile.token) { // 登录 TODO
          // (1) 发送接口
          checkAllCart({
            selected: checked,
            skuId: ctx.getters.effectiveList.map(item => item.skuId)
          }).then(res => {
            // (2) 重新获取最新数据
            findCartList().then(res => {
              // 后端返回的购物车列表覆盖到本地的购物车列表 以后端的列表为主
              ctx.commit('changeList', res.result)
              resolve()
            })
          })
        } else { // 非登陆 本地
          ctx.commit('allCheck', checked)
          resolve()
        }
      })
    },
    // 同步vuex数量
    asyncChangeNum (ctx, { goods, num }) {
      return new Promise((resolve, reject) => {
        if (ctx.rootState.user.profile.token) { // 登录 TODO
          // 准备参数
          const params = {
            skuId: goods.skuId,
            selected: goods.selected,
            count: num
          }
          // (1) 修改数量 发送接口
          updateCart(params).then(res => {
            // (2) 拉取最新数据
            findCartList().then(res => {
              ctx.commit('changeList', res.result)
            })
          })
        } else { // 非登陆
          ctx.commit('changeNum', { goods, num })
          resolve()
        }
      })
    },
    // 合并购物车
    mergeCartList (state) { // mutation中的state参数是一个对象
      console.log('state', state)
      // 1. 准备接口参数(基于现有的数组 返回一个新数组 针对于每一项选取其中三个必要字段)
      const cartList = state.state.list.map((item) => {
        return {
          skuId: item.skuId,
          selected: item.selected,
          count: item.count
        }
      })
      console.log('筛选的数据', cartList)
      // 判断一下list长度
      // if (cartList.length === 0) {
      //   return
      // }
      // 2. 调用合并购物车接口 findCartList
      mergeLocalCart(cartList).then(res => {
        // (1) 调用合并购物车之后重新拉取后端处理过后的最新的购物车列表
        // 调用最新购物车列表findCartList接口获取最新数据
        findCartList().then(res => {
          // (2) 后端返回的购物车列表覆盖到本地的购物车列表 以后端的列表为主
          console.log('后端返回的最新的购物车列表', res)
          state.commit('changeList', res.result)
        })
      })
    }
  },
  //   基于state计算属性
  getters: {
    // 计算有效商品列表(库存大于零且isEffective字段为true)  filter()过滤
    effectiveList (state) {
      console.log('state2', state)
      return state.list.filter(item => item.stock > 0 && item.isEffective)
    },
    // 计算有效商品总数 把effectiveList中的每一项的count叠加
    allCount (state, getters) {
      return getters.effectiveList.reduce((acc, cur) => {
        return acc + cur.count
      }, 0) // 不设置初始值，默认acc是数组第一项
    },
    // 有效商品总金额 = 所有单项的钱数的累加 单项钱数 = 数量 * 单价(防止精度丢失)
    allPrice (state, getters) {
      return getters.effectiveList.reduce((a, c) => a + c.count * c.nowPrice * 100, 0) / 100
    },
    // 已选中商品列表项 selected为true的项
    selectedList (state) {
      return state.list.filter(item => item.selected)
    },
    //  选中商品的总金额 selectedList中所有项的 单价 * 数量
    allSelectedPrice (state, getters) {
      return getters.selectedList.reduce((a, c) => {
        return a + (c.count * c.nowPrice * 100) / 100
      }, 0)
    },
    // 全选: 有效类中的selected字段全为true 全选才为true 选中状态
    isAll (state, getters) {
      return getters.effectiveList.every(item => item.selected)
    }
  }
}
